// 模块隔离管理器
class ModuleIsolationManager {
  constructor() {
    this.isolatedModules = new Map()
    this.styleScopes = new Map()
    this.scriptContexts = new Map()
  }

  /**
   * 为模块创建隔离环境
   * @param {string} moduleName - 模块名称
   * @param {HTMLElement} container - 模块容器
   */
  createIsolation(moduleName, container) {
    const isolation = {
      module: moduleName,
      container: container,
      originalStyles: this.captureStyles(container),
      originalScripts: this.captureScripts(container),
      styleScope: this.generateStyleScope(moduleName),
      scriptContext: this.generateScriptContext(moduleName),
      isActive: false
    }

    this.isolatedModules.set(moduleName, isolation)
    this.applyIsolation(moduleName)
    console.log(`Isolation created for module '${moduleName}'`)
    return isolation
  }

  /**
   * 应用隔离
   * @param {string} moduleName - 模块名称
   */
  applyIsolation(moduleName) {
    const isolation = this.isolatedModules.get(moduleName)
    if (!isolation) return

    const { container, styleScope, scriptContext } = isolation

    // 添加样式作用域
    container.classList.add(styleScope)

    // 隔离脚本上下文
    this.isolateScripts(container, scriptContext)

    isolation.isActive = true
    console.log(`Isolation applied for module '${moduleName}'`)
  }

  /**
   * 移除隔离
   * @param {string} moduleName - 模块名称
   */
  removeIsolation(moduleName) {
    const isolation = this.isolatedModules.get(moduleName)
    if (!isolation) return

    const { container, styleScope, originalStyles, originalScripts } = isolation

    // 移除样式作用域
    container.classList.remove(styleScope)

    // 恢复原始样式
    this.restoreStyles(container, originalStyles)

    // 恢复脚本上下文
    this.restoreScripts(container, originalScripts)

    isolation.isActive = false
    console.log(`Isolation removed for module '${moduleName}'`)
  }

  /**
   * 生成样式作用域类名
   * @param {string} moduleName - 模块名称
   */
  generateStyleScope(moduleName) {
    const scope = `module-${moduleName.replace(/\s+/g, '-').toLowerCase()}`
    this.styleScopes.set(moduleName, scope)
    return scope
  }

  /**
   * 生成脚本上下文名称
   * @param {string} moduleName - 模块名称
   */
  generateScriptContext(moduleName) {
    const context = `module_${moduleName.replace(/\s+/g, '_').toLowerCase()}_context`
    this.scriptContexts.set(moduleName, context)
    return context
  }

  /**
   * 捕获容器中的样式
   * @param {HTMLElement} container - 容器元素
   */
  captureStyles(container) {
    const styles = []
    const styleElements = container.querySelectorAll('style, link[rel="stylesheet"]')

    styleElements.forEach((element, index) => {
      if (element.tagName === 'STYLE') {
        styles.push({
          type: 'style',
          index: index,
          content: element.textContent,
          attributes: this.getElementAttributes(element)
        })
      } else if (element.tagName === 'LINK') {
        styles.push({
          type: 'link',
          index: index,
          href: element.href,
          attributes: this.getElementAttributes(element)
        })
      }
    })

    return styles
  }

  /**
   * 捕获容器中的脚本
   * @param {HTMLElement} container - 容器元素
   */
  captureScripts(container) {
    const scripts = []
    const scriptElements = container.querySelectorAll('script')

    scriptElements.forEach((element, index) => {
      scripts.push({
        type: element.type || 'text/javascript',
        index: index,
        content: element.textContent,
        src: element.src,
        attributes: this.getElementAttributes(element)
      })
    })

    return scripts
  }

  /**
   * 恢复样式
   * @param {HTMLElement} container - 容器元素
   * @param {Array} originalStyles - 原始样式
   */
  restoreStyles(container, originalStyles) {
    // 移除所有现有的样式元素
    container.querySelectorAll('style, link[rel="stylesheet"]').forEach(el => el.remove())

    // 重新插入原始样式
    originalStyles.forEach(style => {
      const element = document.createElement(style.type === 'link' ? 'link' : 'style')

      if (style.type === 'link') {
        element.href = style.href
        element.rel = 'stylesheet'
      } else {
        element.textContent = style.content
      }

      // 恢复属性
      Object.keys(style.attributes).forEach(key => {
        if (key !== 'type' && key !== 'index') {
          element.setAttribute(key, style.attributes[key])
        }
      })

      container.appendChild(element)
    })
  }

  /**
   * 恢复脚本
   * @param {HTMLElement} container - 容器元素
   * @param {Array} originalScripts - 原始脚本
   */
  restoreScripts(container, originalScripts) {
    // 移除所有现有的脚本元素
    container.querySelectorAll('script').forEach(el => el.remove())

    // 重新插入原始脚本
    originalScripts.forEach(script => {
      const element = document.createElement('script')
      element.type = script.type

      if (script.src) {
        element.src = script.src
      } else if (script.content) {
        element.textContent = script.content
      }

      // 恢复属性
      Object.keys(script.attributes).forEach(key => {
        if (key !== 'type' && key !== 'index') {
          element.setAttribute(key, script.attributes[key])
        }
      })

      container.appendChild(element)
    })
  }

  /**
   * 隔离脚本上下文
   * @param {HTMLElement} container - 容器元素
   * @param {string} contextName - 上下文名称
   */
  isolateScripts(container, contextName) {
    const scriptElements = container.querySelectorAll('script')

    scriptElements.forEach(element => {
      if (element.textContent) {
        // 为内联脚本创建包装
        const wrappedCode = `
          (function() {
            'use strict';
            var ${contextName} = {};
            // 模块代码将在这里执行
            ${element.textContent}
          })();
        `
        element.textContent = wrappedCode
      }

      // 添加上下文属性
      element.setAttribute('data-module-context', contextName)
    })
  }

  /**
   * 获取元素属性
   * @param {HTMLElement} element - 元素
   */
  getElementAttributes(element) {
    const attributes = {}
    for (let attr of element.attributes) {
      attributes[attr.name] = attr.value
    }
    return attributes
  }

  /**
   * 检查模块是否已隔离
   * @param {string} moduleName - 模块名称
   */
  isIsolated(moduleName) {
    const isolation = this.isolatedModules.get(moduleName)
    return isolation ? isolation.isActive : false
  }

  /**
   * 获取所有隔离的模块
   */
  getIsolatedModules() {
    return Array.from(this.isolatedModules.values()).filter(module => module.isActive)
  }

  /**
   * 清理所有隔离
   */
  cleanup() {
    this.isolatedModules.forEach((isolation, moduleName) => {
      this.removeIsolation(moduleName)
    })
    this.isolatedModules.clear()
    this.styleScopes.clear()
    this.scriptContexts.clear()
  }
}

// 创建全局实例
const moduleIsolationManager = new ModuleIsolationManager()

export default moduleIsolationManager
export { ModuleIsolationManager }